Interactive Features

**Referenced Files in This Document** - [main.js](file://src/assets/js/main.js) - [navigation.js](file://src/assets/js/modules/navigation.js) - [theme-toggling.js](file://src/assets/js/modules/theme-toggling.js) - [custom-cursor.js](file://src/assets/js/modules/custom-cursor.js) - [carousel-system.js](file://src/assets/js/modules/carousel-system.js) - [search-functionality.js](file://src/assets/js/modules/search-functionality.js) - [04-navigation.css](file://src/assets/css/modules/04-navigation.css) - [08-carousel-shared-infrastructure.css](file://src/assets/css/modules/08-carousel-shared-infrastructure.css) - [41-search-modal.css](file://src/assets/css/modules/41-search-modal.css) - [03-custom-cursor.css](file://src/assets/css/modules/03-custom-cursor.css) - [38-material-design-3-theme-toggle.css](file://src/assets/css/modules/38-material-design-3-theme-toggle.css) - [base.njk](file://src/_includes/layouts/base.njk)

Table of Contents

  1. Introduction
  2. Project Structure
  3. Core Components
  4. Architecture Overview
  5. Detailed Component Analysis
  6. Dependency Analysis
  7. Performance Considerations
  8. Troubleshooting Guide
  9. Conclusion
  10. Appendices

Introduction

This document explains the interactive features and JavaScript modules that power the website’s dynamic user experience. It covers:

  • The carousel system for capabilities, testimonials, and news with touch and keyboard navigation
  • The search functionality powered by Pagefind, including indexing, query processing, and result presentation
  • The theme switching system using IntersectionObserver for automatic dark/light mode detection
  • The navigation system including mobile menu behavior and responsive behavior
  • Custom cursor effects and animation systems It also provides practical usage examples, customization options, integration patterns, performance guidance, accessibility notes, and cross-browser considerations.

Project Structure

The interactive features are implemented as modular JavaScript functions imported and initialized in the main entry point. Styles are organized per-feature in dedicated CSS modules and integrated via the global stylesheet.

graph TB
JSMain["src/assets/js/main.js"]
NavJS["src/assets/js/modules/navigation.js"]
ThemeToggleJS["src/assets/js/modules/theme-toggling.js"]
CursorJS["src/assets/js/modules/custom-cursor.js"]
CarouselJS["src/assets/js/modules/carousel-system.js"]
SearchJS["src/assets/js/modules/search-functionality.js"]
CSSNav["src/assets/css/modules/04-navigation.css"]
CSSCarousel["src/assets/css/modules/08-carousel-shared-infrastructure.css"]
CSSSearch["src/assets/css/modules/41-search-modal.css"]
CSSCursor["src/assets/css/modules/03-custom-cursor.css"]
CSSMD3["src/assets/css/modules/38-material-design-3-theme-toggle.css"]
BaseHTML["src/_includes/layouts/base.njk"]
JSMain --> NavJS
JSMain --> ThemeToggleJS
JSMain --> CursorJS
JSMain --> CarouselJS
JSMain --> SearchJS
BaseHTML --> CSSNav
BaseHTML --> CSSCarousel
BaseHTML --> CSSSearch
BaseHTML --> CSSCursor
BaseHTML --> CSSMD3

Diagram sources

  • [main.js:15-36](file://src/assets/js/main.js#L15-L36)
  • [navigation.js:3-75](file://src/assets/js/modules/navigation.js#L3-L75)
  • [theme-toggling.js:3-21](file://src/assets/js/modules/theme-toggling.js#L3-L21)
  • [custom-cursor.js:3-25](file://src/assets/js/modules/custom-cursor.js#L3-L25)
  • [carousel-system.js:3-166](file://src/assets/js/modules/carousel-system.js#L3-L166)
  • [search-functionality.js:3-176](file://src/assets/js/modules/search-functionality.js#L3-L176)
  • [04-navigation.css:1-101](file://src/assets/css/modules/04-navigation.css#L1-L101)
  • [08-carousel-shared-infrastructure.css:1-90](file://src/assets/css/modules/08-carousel-shared-infrastructure.css#L1-L90)
  • [41-search-modal.css:1-314](file://src/assets/css/modules/41-search-modal.css#L1-L314)
  • [03-custom-cursor.css:1-46](file://src/assets/css/modules/03-custom-cursor.css#L1-L46)
  • [38-material-design-3-theme-toggle.css:1-237](file://src/assets/css/modules/38-material-design-3-theme-toggle.css#L1-L237)
  • [base.njk:63-258](file://src/_includes/layouts/base.njk#L63-L258)

Section sources

  • [main.js:15-36](file://src/assets/js/main.js#L15-L36)
  • [base.njk:63-258](file://src/_includes/layouts/base.njk#L63-L258)

Core Components

  • Navigation: Mobile-friendly navigation with animated hamburger menu, focus trapping, and escape-to-close behavior.
  • Theme Toggling: Automatic theme switching using IntersectionObserver to detect section themes and apply body classes.
  • Custom Cursor: Desktop-only animated cursor with GSAP-powered smooth motion and hover states.
  • Carousel System: Multi-purpose carousel supporting click, keyboard, and drag-to-scroll with pagination dots.
  • Search Modal: Pagefind-powered search with debounced input, keyboard navigation, and result categorization.

Section sources

  • [navigation.js:3-75](file://src/assets/js/modules/navigation.js#L3-L75)
  • [theme-toggling.js:3-21](file://src/assets/js/modules/theme-toggling.js#L3-L21)
  • [custom-cursor.js:3-25](file://src/assets/js/modules/custom-cursor.js#L3-L25)
  • [carousel-system.js:3-166](file://src/assets/js/modules/carousel-system.js#L3-L166)
  • [search-functionality.js:3-176](file://src/assets/js/modules/search-functionality.js#L3-L176)

Architecture Overview

The initialization flow wires all interactive modules on DOMContentLoaded. The search module lazily loads Pagefind on demand. Carousels and navigation are self-contained and rely on accessible markup and ARIA attributes. Theme toggling observes section boundaries to switch body classes for consistent theming.

sequenceDiagram
participant DOM as "DOM"
participant Main as "main.js"
participant Nav as "navigation.js"
participant Theme as "theme-toggling.js"
participant Cursor as "custom-cursor.js"
participant Carousel as "carousel-system.js"
participant Search as "search-functionality.js"
DOM->>Main : "DOMContentLoaded"
Main->>Nav : "initNavigation()"
Main->>Theme : "initThemeToggling()"
Main->>Carousel : "initCarousels()"
Main->>Search : "initSearch()"
Main->>Cursor : "initCustomCursor() (if GSAP available)"

Diagram sources

  • [main.js:15-36](file://src/assets/js/main.js#L15-L36)
  • [navigation.js:3-75](file://src/assets/js/modules/navigation.js#L3-L75)
  • [theme-toggling.js:3-21](file://src/assets/js/modules/theme-toggling.js#L3-L21)
  • [custom-cursor.js:3-25](file://src/assets/js/modules/custom-cursor.js#L3-L25)
  • [carousel-system.js:3-166](file://src/assets/js/modules/carousel-system.js#L3-L166)
  • [search-functionality.js:3-176](file://src/assets/js/modules/search-functionality.js#L3-L176)

Detailed Component Analysis

Navigation System

  • Responsibilities:
    • Toggle mobile menu with animated hamburger state
    • Focus management: trap focus inside the menu and restore focus on close
    • Close on Escape, click outside, or selecting a link
    • Accessibility: ARIA-expanded, aria-label updates, and keyboard navigation
  • Implementation highlights:
    • Uses CSS classes to animate the menu and body lock
    • Listens to keydown events for Tab trapping and Escape
    • Closes automatically when a link is clicked
sequenceDiagram
participant User as "User"
participant Toggle as "Nav Toggle"
participant Menu as "Nav Menu"
participant Body as "Body"
User->>Toggle : "Click"
Toggle->>Menu : "Add 'active'"
Toggle->>Body : "Add 'menu-open'"
Toggle->>Toggle : "Set aria-expanded=true"
User->>Menu : "Press Escape"
Menu->>Toggle : "Remove 'active'"
Menu->>Body : "Remove 'menu-open'"
Toggle->>Toggle : "Set aria-expanded=false"

Diagram sources

  • [navigation.js:8-46](file://src/assets/js/modules/navigation.js#L8-L46)
  • [base.njk:92-94](file://src/_includes/layouts/base.njk#L92-L94)

Section sources

  • [navigation.js:3-75](file://src/assets/js/modules/navigation.js#L3-L75)
  • [04-navigation.css:1-101](file://src/assets/css/modules/04-navigation.css#L1-L101)
  • [base.njk:70-95](file://src/_includes/layouts/base.njk#L70-L95)

Theme Switching System (IntersectionObserver)

  • Responsibilities:
    • Observe sections with data-theme to set body classes for on-light-bg/on-dark-bg
    • Adjust UI affordances (e.g., carousel buttons) based on current theme
  • Implementation highlights:
    • Root margin set to center the viewport for accurate theme detection
    • Prevents redundant theme changes by tracking current theme
flowchart TD
Start(["Init Theme Toggling"]) --> Observe["Observe sections with data-theme"]
Observe --> Entry{"Entry intersects?"}
Entry --> |No| Wait["Wait for intersection"]
Entry --> |Yes| ReadTheme["Read dataset.theme"]
ReadTheme --> Same{"Same as current?"}
Same --> |Yes| Wait
Same --> |No| Apply["Toggle body classes:<br/>on-light-bg / on-dark-bg"]
Apply --> Wait

Diagram sources

  • [theme-toggling.js:9-20](file://src/assets/js/modules/theme-toggling.js#L9-L20)

Section sources

  • [theme-toggling.js:3-21](file://src/assets/js/modules/theme-toggling.js#L3-L21)
  • [38-material-design-3-theme-toggle.css:17-33](file://src/assets/css/modules/38-material-design-3-theme-toggle.css#L17-L33)

Custom Cursor Effects and Animation Systems

  • Responsibilities:
    • Provide desktop-only animated cursor with GSAP
    • Scale and style follower differently on hover targets
    • Hide cursor on coarse-pointer devices or small screens
  • Implementation highlights:
    • Uses GSAP.set for initial positioning and GSAP.to for smooth movement
    • Adds/removes hover class on mouseenter/mouseleave for targets
flowchart TD
Init(["Init Custom Cursor"]) --> Detect["Detect coarse pointer or small screen"]
Detect --> |Match| Hide["Hide cursors"]
Detect --> |No match| Setup["GSAP set positions"]
Setup --> MouseMove["Listen to mousemove"]
MouseMove --> Animate["GSAP to positions with easing"]
Animate --> Targets["Attach hover listeners to targets"]
Targets --> Hover["Toggle hover classes"]

Diagram sources

  • [custom-cursor.js:8-24](file://src/assets/js/modules/custom-cursor.js#L8-L24)
  • [03-custom-cursor.css:15-39](file://src/assets/css/modules/03-custom-cursor.css#L15-L39)

Section sources

  • [custom-cursor.js:3-25](file://src/assets/js/modules/custom-cursor.js#L3-L25)
  • [03-custom-cursor.css:1-46](file://src/assets/css/modules/03-custom-cursor.css#L1-L46)

Carousel System (Capabilities, Testimonials, News)

  • Responsibilities:
    • Paginate horizontally with previous/next buttons and keyboard arrows
    • Render pagination dots with snap points derived from viewport and items
    • Support drag-to-scroll with minimal movement threshold
    • Update active dot and button opacity based on scroll position
  • Implementation highlights:
    • Calculates items per page from computed styles and gaps
    • Uses passive scroll and resize listeners for performance
    • Sets ARIA attributes for accessibility
flowchart TD
Start(["Init Carousels"]) --> Configs["Load configs for capabilities/testimonials/news"]
Configs --> Setup["setupCarousel(cfg)"]
Setup --> Find["Find viewport, track, items"]
Find --> Dots["Render dots and compute snap points"]
Dots --> Events["Bind prev/next click, keyboard arrows,<br/>drag mouse events"]
Events --> Update["Update active dot and button states"]
Update --> Passive["Passive listeners for scroll/resize"]

Diagram sources

  • [carousel-system.js:3-119](file://src/assets/js/modules/carousel-system.js#L3-L119)
  • [08-carousel-shared-infrastructure.css:5-87](file://src/assets/css/modules/08-carousel-shared-infrastructure.css#L5-L87)

Section sources

  • [carousel-system.js:3-166](file://src/assets/js/modules/carousel-system.js#L3-L166)
  • [08-carousel-shared-infrastructure.css:1-90](file://src/assets/css/modules/08-carousel-shared-infrastructure.css#L1-L90)

Search Functionality (Pagefind)

  • Responsibilities:
    • Open/close modal with overlay and keyboard shortcuts
    • Debounced input handling to limit Pagefind calls
    • Keyboard navigation among results (arrow keys, enter, escape)
    • Categorize and present results with icons and excerpts
  • Implementation highlights:
    • Lazy-loads Pagefind module and sets excerpt length
    • Clears selection when closing modal or clearing input
    • Supports global shortcut to open search (Cmd/Ctrl+K)
sequenceDiagram
participant User as "User"
participant Toggle as ".search-toggle"
participant Modal as ".search-modal"
participant Input as "#search-input"
participant PF as "Pagefind"
User->>Toggle : "Click"
Toggle->>Modal : "Add 'active', set aria-hidden=false"
Modal->>Input : "Focus after delay"
User->>Input : "Type"
Input->>Input : "Debounce timer"
Input->>PF : "performSearch(query)"
PF-->>Input : "Results"
Input->>Modal : "Render results with categories"
User->>Input : "ArrowDown/Up/Enter"
Input->>Modal : "Update selection and navigate"
User->>Modal : "Escape or overlay click"
Modal->>Modal : "Remove 'active', reset state"

Diagram sources

  • [search-functionality.js:30-176](file://src/assets/js/modules/search-functionality.js#L30-L176)
  • [41-search-modal.css:34-288](file://src/assets/css/modules/41-search-modal.css#L34-L288)
  • [base.njk:87-127](file://src/_includes/layouts/base.njk#L87-L127)

Section sources

  • [search-functionality.js:3-176](file://src/assets/js/modules/search-functionality.js#L3-L176)
  • [41-search-modal.css:1-314](file://src/assets/css/modules/41-search-modal.css#L1-L314)
  • [base.njk:87-127](file://src/_includes/layouts/base.njk#L87-L127)

Dependency Analysis

  • Initialization order ensures core features are ready before optional animations.
  • Search depends on Pagefind being available; it is loaded lazily to avoid blocking initial load.
  • Carousels and navigation are self-contained and rely on accessible DOM structure.
  • Theme toggling observes sections and toggles body classes for downstream styling.
graph LR
Main["main.js"] --> Nav["navigation.js"]
Main --> Theme["theme-toggling.js"]
Main --> Cursor["custom-cursor.js"]
Main --> Carousel["carousel-system.js"]
Main --> Search["search-functionality.js"]
Search --> Pagefind["Pagefind (dynamic import)"]

Diagram sources

  • [main.js:15-36](file://src/assets/js/main.js#L15-L36)
  • [search-functionality.js:18-28](file://src/assets/js/modules/search-functionality.js#L18-L28)

Section sources

  • [main.js:15-36](file://src/assets/js/main.js#L15-L36)
  • [search-functionality.js:18-28](file://src/assets/js/modules/search-functionality.js#L18-L28)

Performance Considerations

  • Event listeners use passive options for scroll and resize to improve scrolling performance.
  • Debouncing limits frequent Pagefind calls during typing.
  • Lazy loading of Pagefind reduces initial bundle size.
  • IntersectionObserver avoids layout thrashing by batching theme updates.
  • GSAP animations are conditionally enabled; if unavailable, core features remain functional.
  • Consider virtualizing long carousels or limiting result count to reduce DOM and layout costs.

[No sources needed since this section provides general guidance]

Troubleshooting Guide

  • Search modal does not open:
    • Ensure the toggle and modal elements exist in the DOM.
    • Verify Pagefind is accessible at the expected path.
  • Pagefind unavailable:
    • Confirm network availability and correct path; the module logs a warning when unavailable.
  • Carousels not rendering dots:
    • Check that items are rendered before initialization and that viewport/clientWidth is measurable.
  • Navigation menu not closing:
    • Confirm event listeners are attached and that Escape or click-outside conditions are met.
  • Custom cursor not visible:
    • On coarse-pointer devices or small screens, the cursor hides by design.
  • Theme not switching:
    • Ensure sections have the data-theme attribute and that IntersectionObserver is supported.

Section sources

  • [search-functionality.js:12-28](file://src/assets/js/modules/search-functionality.js#L12-L28)
  • [carousel-system.js:18-22](file://src/assets/js/modules/carousel-system.js#L18-L22)
  • [navigation.js:6, 34-46:6-46](file://src/assets/js/modules/navigation.js#L6-L46)
  • [custom-cursor.js:8-12](file://src/assets/js/modules/custom-cursor.js#L8-L12)
  • [theme-toggling.js:4-5](file://src/assets/js/modules/theme-toggling.js#L4-L5)

Conclusion

The interactive features are modular, accessible, and optimized for performance. They integrate cleanly with the existing CSS architecture and provide a cohesive user experience across devices. Extending these features involves adding new modules following the established initialization pattern and ensuring ARIA and accessibility best practices.

[No sources needed since this section summarizes without analyzing specific files]

Appendices

Practical Usage Examples and Customization Options

  • Initialize modules:
    • Call the exported init functions in main.js for navigation, theme toggling, carousels, search, and optionally custom cursor/animations.
  • Customize carousels:
    • Add new carousel configurations with unique IDs for track, prev, next, and optional dots container.
    • Adjust CSS grid or flex layout to change items-per-page and spacing.
  • Extend search:
    • Add new result categories by expanding URL-based classification logic.
    • Tune debounce timing and excerpt length via Pagefind options.
  • Enhance navigation:
    • Add more focus traps or keyboard shortcuts as needed.
  • Improve theme detection:
    • Add more granular section markers or thresholds to refine theme transitions.

Section sources

  • [main.js:15-36](file://src/assets/js/main.js#L15-L36)
  • [carousel-system.js:4-10](file://src/assets/js/modules/carousel-system.js#L4-L10)
  • [search-functionality.js:21-22](file://src/assets/js/modules/search-functionality.js#L21-L22)

Accessibility Features

  • Carousels:
    • ARIA roles and labels applied to viewport and buttons; keyboard navigation supported.
  • Navigation:
    • ARIA-expanded and aria-controls on toggle; focus trapped inside menu; Escape closes menu.
  • Search:
    • Modal managed with aria-hidden; keyboard navigation among results; global shortcut to open.
  • Theme Toggle:
    • Role="switch" and aria-checked for assistive technologies.

Section sources

  • [carousel-system.js:121-132](file://src/assets/js/modules/carousel-system.js#L121-L132)
  • [navigation.js:8-27](file://src/assets/js/modules/navigation.js#L8-L27)
  • [search-functionality.js:30-46](file://src/assets/js/modules/search-functionality.js#L30-L46)
  • [base.njk:235-252](file://src/_includes/layouts/base.njk#L235-L252)

Cross-Browser Compatibility Considerations

  • IntersectionObserver: Falls back gracefully if unsupported; ensure polyfills if targeting older browsers.
  • Pagefind dynamic import: Requires modern browser support; handle errors and provide fallback UI.
  • GSAP: Optional; if unavailable, core features remain active while animations are skipped.
  • CSS Grid/Flexbox: Used extensively; verify vendor prefixes if legacy support is required.
  • Pointer media queries: Cursor hides on coarse pointers; ensure alternative interaction methods for mobile.

Section sources

  • [theme-toggling.js:9-20](file://src/assets/js/modules/theme-toggling.js#L9-L20)
  • [search-functionality.js:18-28](file://src/assets/js/modules/search-functionality.js#L18-L28)
  • [custom-cursor.js:8-12](file://src/assets/js/modules/custom-cursor.js#L8-L12)
  • [main.js:28-35](file://src/assets/js/main.js#L28-L35)